package com.crocodileq.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.crocodileq.dto.Result;
import com.crocodileq.dto.UserDTO;
import com.crocodileq.entity.SeckillVoucher;
import com.crocodileq.entity.VoucherOrder;
import com.crocodileq.mapper.SeckillVoucherMapper;
import com.crocodileq.mapper.VoucherMapper;
import com.crocodileq.mapper.VoucherOrderMapper;
import com.crocodileq.service.IVoucherOrderService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.crocodileq.utils.RedisIdWorker;
import com.crocodileq.utils.UserHolder;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDateTime;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author 虎哥
 * @since 2021-12-22
 */
@Service
public class VoucherOrderServiceImpl extends ServiceImpl<VoucherOrderMapper, VoucherOrder> implements IVoucherOrderService {


    @Resource
    private VoucherOrderMapper voucherOrderMapper;

    @Resource
    private VoucherMapper voucherMapper;

    @Resource
    private SeckillVoucherMapper seckillVoucherMapper;

    @Resource
    private RedisIdWorker redisIdWorker;

    @Autowired
    private ApplicationContext context;

    @Resource
    private RedissonClient redissonClient;


    public Result seckillVoucher(Long voucherId) {

        // 查询秒杀优惠券信息
        SeckillVoucher seckillVoucher = seckillVoucherMapper.selectById(voucherId);

        //判断秒杀是否开始
        //未开始或已结束，返回异常信息
        if (seckillVoucher.getBeginTime().isAfter(LocalDateTime.now())){
            return Result.fail("秒杀尚未开始");
        }

        if (seckillVoucher.getEndTime().isBefore(LocalDateTime.now())){
            return Result.fail("秒杀已结束");
        }

        //开始，判断库存是否充足
        //不足，返回异常信息
        if (seckillVoucher.getStock() < 1){
            return Result.fail("库存不足");
        }


       return createOrder(voucherId);
    }

    /**
     * 创建优惠券订单
     * @param voucherId
     * @return
     */
    @Transactional
    public Result createOrder(Long voucherId) {

        //一人一单
        //充足，根据优惠券id和用户id查询订单
        UserDTO user = UserHolder.getUser();
        Long userId = user.getId();

        Long count = query().eq("user_id", userId).eq("voucher_id", voucherId).count();

        //订单存在，返回：您已下过单了
        if(count > 0 ){
            return Result.fail("您已下过单了");
        }
        //获取锁，应对并发问题
        RLock lock = redissonClient.getLock("lock:order:" + userId);
        boolean isLock = lock.tryLock();

        if(!isLock){
            //获取锁失败，返回异常信息
            return Result.fail("不允许重复下单");
        }
        try {
            VoucherOrder voucherOrder;
            seckillVoucherMapper.update(null,
                    new LambdaUpdateWrapper<SeckillVoucher>()
                            .setSql("stock = stock - 1")
                            .eq(SeckillVoucher::getVoucherId, voucherId)
                            .gt(SeckillVoucher::getStock, 0)
            );

            // 创建订单
            long orderId = redisIdWorker.nextId(Thread.currentThread().getName());
            voucherOrder =  new VoucherOrder();
            voucherOrder.setId(orderId);
            voucherOrder.setUserId(user.getId());
            voucherOrder.setVoucherId(voucherId);

            voucherOrderMapper.insert(voucherOrder);

            //返回订单id
            return Result.ok(orderId);
        }finally {
            lock.unlock();
        }
    }
}
